/*
\ brief:  实现文件
\ author: 清晨与猫鱼
*/
#include <iostream>     // 标准输入输出库
#include <mutex>        // 线程锁

/*
\ brief :  懒汉版本
\ author : 清晨与猫鱼
*/
class SingleObject {  
public:  

/*
\ brief:  获取唯一示例
\ author: 清晨与猫鱼
*/
    static SingleObject& GetInstance()  
    {  
        if (object == nullptr) { 
            object = new SingleObject;  
        }
        return *object;  
    }  

/*
\ brief:   显示信息
\ author: 清晨与猫鱼
*/ 
    void showMessage() {
        std::cout << "hello word" << std::endl;
    }

private:  
    explicit SingleObject (){};         // 构造函数私有化
    static SingleObject* object;        // 静态变量指针

    SingleObject(const SingleObject&) = delete;     // 删除拷贝构造
    SingleObject(SingleObject&&) = delete;          // 删除移动
};


SingleObject* SingleObject::object = nullptr;       // 初始化之后才能使用




/*
\ brief :  饿汉版本
\ author : 清晨与猫鱼
*/
class SingleObjectT {
public: 

/*
\ brief:    获取唯一实例
\ author: 清晨与猫鱼
*/
    static SingleObjectT& GetInstance() {  
        static SingleObjectT object;        // 局部静态变量
        return object;      
    }  

    void showMessage() {
        std::cout << "hello word" << std::endl;
    }

private:
    explicit SingleObjectT (){ };  
    SingleObjectT(const SingleObjectT&) = delete;
    SingleObjectT(SingleObjectT&&) = delete;
}; 




/*
\ brief :  多线程版本
\ author : 清晨与猫鱼
*/
class SingleObjectTT {  
public:  

/*
\ brief:    获取多线程版本唯一实例
\ author: 清晨与猫鱼
*/
    static SingleObjectTT& GetInstance()  {   

        bool flag(false);       // 局部变量 设置false

        // 先锁住，然后判断指针是否为nullptr
        SingleObjectTT::m.lock();
        if (object == nullptr) {
            flag = true;        // 是的化，改变局部变量的值
        }
        SingleObjectTT::m.unlock();     // 解锁
 
        // 如果flag 标志被设置为true
        if (flag == true) {
            object = new SingleObjectTT();      // new一个实例
        }          
        return *object;     
    }  

    void showMessage() {
        std::cout << "hello word" << std::endl;
    }

private:  
    explicit SingleObjectTT (){};  
    static SingleObjectTT * object;         // 变量的指针
    static std::mutex m;                    // 锁
    SingleObjectTT(const SingleObjectTT&) = delete;
    SingleObjectTT(SingleObjectTT&&) = delete;
};


SingleObjectTT* SingleObjectTT::object = nullptr;       // 初始化
std::mutex SingleObjectTT::m;                            // 初始化
